package mtm.ui.list;


import java.awt.Toolkit;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;

import javax.swing.JOptionPane;

import mtm.db.DatabaseHandler;
import mtm.db.Job;


public class DndList extends JobList implements
		DropTargetListener, DragSourceListener, DragGestureListener {

	/**
	 * enables this component to be a dropTarget
	 */
	private DropTarget dropTarget = null;

	/**
	 * enables this component to be a Drag Source
	 */
	private DragSource dragSource = null;
	
	
	/**
	 * constructor - initializes the DropTarget and DragSource.
	 */
	public DndList(int date) {
		super(date);
		dropTarget = new DropTarget(this, this);
		dragSource = new DragSource();
		dragSource.createDefaultDragGestureRecognizer(this,
				DnDConstants.ACTION_MOVE, this);
	}

	/**
	 * is invoked when you are dragging over the DropSite
	 * 
	 */

	public void dragEnter(DropTargetDragEvent event) {
		event.acceptDrag(DnDConstants.ACTION_MOVE);
	}

	/**
	 * is invoked when you are exit the DropSite without dropping
	 * 
	 */

	public void dragExit(DropTargetEvent event) {

	}

	/**
	 * is invoked when a drag operation is going on
	 * 
	 */

	public void dragOver(DropTargetDragEvent event) {
	}

	/**
	 * a drop has occurred
	 * 
	 */

	public void drop(DropTargetDropEvent event) {
		
		try {
			Transferable transferable = event.getTransferable();
			if (transferable.isDataFlavorSupported(JobDataFlavor.getInstance())) {
				// reject drop if this List has no date title
				if (getDate() == NO_DATE) {
					event.rejectDrop();
					Toolkit.getDefaultToolkit().beep();
					return;
				}
				
				// accept drop action
				event.acceptDrop(DnDConstants.ACTION_MOVE);
				JobItem item = (JobItem) 
					transferable.getTransferData(JobDataFlavor.getInstance());
				addItem(item);
				event.getDropTargetContext().dropComplete(true);
				
				// update job when end drag and drop process
				Job job = item.getJob();
				job.getStartTime().setDate(getDate());
				job.getEndTime().setDate(getDate());
				DatabaseHandler.getInstance().updateJob(job, item.getId());
			} else {
				event.rejectDrop();
			}
			
		} catch (IOException exception) {
			exception.printStackTrace();
			System.err.println("Exception" + exception.getMessage());
			event.rejectDrop();
		} catch (UnsupportedFlavorException ufException) {
			ufException.printStackTrace();
			System.err.println("Exception" + ufException.getMessage());
			event.rejectDrop();
		}
	}

	/**
	 * is invoked if the use modifies the current drop gesture
	 * 
	 */

	public void dropActionChanged(DropTargetDragEvent event) {
	}

	/**
	 * a drag gesture has been initiated
	 * 
	 */

	public void dragGestureRecognized(DragGestureEvent event) {
		
		JobItem selectedItem = (JobItem) getSelectedValue();
		if (selectedItem != null) {
			JobTransferable transferable = new JobTransferable(selectedItem);
			// TODO custom cursor when moving item
			// toolkit.createCustomCursor
			
			// date title item can't be dragged
			if (selectedItem.isDragable()) {
				// item of job generated from RepeatJob can't be dragged too
				// parentId of generated job = -1
				if (selectedItem.getJob().getParentId() == -1) {
					dragSource.startDrag(event, DragSource.DefaultMoveDrop, transferable, this);
				} else {
					Toolkit.getDefaultToolkit().beep();
				}
			} else {
				Toolkit.getDefaultToolkit().beep();
			}
		} 
	}

	/**
	 * this message goes to DragSourceListener, informing it that the dragging
	 * has ended
	 * 
	 */

	public void dragDropEnd(DragSourceDropEvent event) {
		if (event.getDropSuccess()) {
			removeSelectedItem();
		}
	}

	/**
	 * this message goes to DragSourceListener, informing it that the dragging
	 * has entered the DropSite
	 * 
	 */

	public void dragEnter(DragSourceDragEvent event) {
	}

	/**
	 * this message goes to DragSourceListener, informing it that the dragging
	 * has exited the DropSite
	 * 
	 */

	public void dragExit(DragSourceEvent event) {

	}

	/**
	 * this message goes to DragSourceListener, informing it that the dragging
	 * is currently ocurring over the DropSite
	 * 
	 */

	public void dragOver(DragSourceDragEvent event) {

	}

	/**
	 * is invoked when the user changes the dropAction
	 * 
	 */

	public void dropActionChanged(DragSourceDragEvent event) {
	}

}
